#include <stdio.h>
#include <opencv2/opencv.hpp>
#include <fstream>
#include <iostream>
#include <armadillo>
#include <iomanip>
#include <vector>

using namespace std;
using namespace arma;

#include "fisher_vector_def.hpp"
#include "fisher_vector_impl.hpp"



//NICTA-QUT
const std::string single_path = "/home/johanna/codes/datasets_codes/weizmann/original/"; 
const std::string multi_path = "/home/johanna/codes/datasets_codes/weizmann/stitched_original/";

//NICTA-QUT Mask datset
const std::string single_path_mask = "/home/johanna/codes/datasets_codes/weizmann/mask/"; 
const std::string multi_path_mask = "/home/johanna/codes/datasets_codes/weizmann/stitched_mask/";

//home
//const std::string single_path = "/media/johanna/HD1T/codes/datasets_codes/weizmann/original/"; 
//const std::string multi_path =  "/media/johanna/HD1T/codes/datasets_codes/weizmann/stitched_original/";

//home-Mask Dataset
//const std::string single_path_mask = "/media/sdb1/codes/datasets_codes/weizmann/mask/"; 
//const std::string multi_path_mask = "/media/sdb1/codes/datasets_codes/weizmann/stitched_mask/";


const std::string  actionNames = "actionNames.txt";
const std::string  peopleList = "people_list.txt";

//Number of samples used per training and testing
uword n_train = 8;
uword n_test  = 1;

///cambiar!!!!!!!!!!!!
//Image Size
//uword ro = 72;
//uword co = 90;

uword ro = 144;
uword co = 180;

void opt_flow_system( field<string> people, int N_cent );
void edt_system( field<string> people, int N_cent );
void mask_opt_flow_system( field<string> people, int N_cent );
void rand_split(int run);

int
main(int argc, char** argv)
{
  
  int N_cent = 4;
  field<string> people;
  people.load(peopleList);
  people.print("All People");
  
  
  ///Run the optical Flow System
  //opt_flow_system(people, N_cent);
 
  ///Run the Euclidean Distance Transform System
  //edt_system(people, N_cent);
  
   ///Run Mask + Pptical Flow System
  mask_opt_flow_system(people, N_cent);
  
  return 0;
  
}

void
mask_opt_flow_system( field<string> people, int N_cent )
{
   ///I Only need to run these once
  //fisher_vector FV(single_path, multi_path, actionNames, co, ro);
  //FV.mask_optflow_features_allpeople(people, single_path_mask); 
  //FV.mask_optflow_features_testing(people, multi_path_mask);
  
  
  
 
   for (int r=1; r<=people.n_rows; r++)//people.n_rows
  {
    int run = r;
    cout << "****************************************" << endl;
    cout << "Doing for run= " << run << endl;
    cout << "N_cent " << N_cent << endl;
    cout << "****************************************" << endl;
  
    
    rand_split(run);
    field<string> peo_train;
    field<string> peo_test;
    std::stringstream train_list;
    train_list<< "./run" << run << "/train_list_run"<< run << ".dat";
    std::stringstream test_list;
    test_list<< "./run" << run << "/test_list_run"<< run << ".dat";
    peo_train.load( train_list.str() );
    peo_test.load(  test_list.str() );
    
    peo_train.print("People Train");
    
    cout << "Calculating Universal GMM" << endl;
    fisher_vector FV2(single_path, multi_path, actionNames, co, ro);
    FV2.mask_optflow_create_universal_gmm(peo_train, N_cent, run); 

   }



}





void
edt_system( field<string> people, int N_cent )
{
   //I Only need to run these once
  //fisher_vector fisher_vector_1(single_path, multi_path, actionNames, co, ro);
  //fisher_vector_1.edt_features_allpeople(people, single_path_mask); 
  //fisher_vector_1.edt_features_testing(people, multi_path_mask);
  
  bool is_pca = false;

   for (int r=1; r<=people.n_rows; r++)//people.n_rows
  {
    int run = r;
    cout << "****************************************" << endl;
    cout << "Doing for run= " << run << endl;
    cout << "N_cent " << N_cent << endl;
    cout << "****************************************" << endl;
  
    
    rand_split(run);
    field<string> peo_train;
    field<string> peo_test;
    std::stringstream train_list;
    train_list<< "./run" << run << "/train_list_run"<< run << ".dat";
    std::stringstream test_list;
    test_list<< "./run" << run << "/test_list_run"<< run << ".dat";
    peo_train.load( train_list.str() );
    peo_test.load(  test_list.str() );
    
    peo_train.print("People Train");
    
    cout << "Calculating Universal GMM" << endl;
    fisher_vector fisher_vector_2(single_path, multi_path, actionNames, co, ro);
    fisher_vector_2.edt_create_universal_gmm(peo_train, N_cent, run, is_pca); 
    //cout << "Press a key... " << endl;
    //getchar();

   }

}



void
opt_flow_system( field<string> people, int N_cent )
{
   ///I Only need to run these once
  //fisher_vector fisher_vector(single_path, multi_path, actionNames, co, ro);
  //fisher_vector.optflow_features_allpeople(people); 
  //fisher_vector.optflow_features_testing(people);
  
  
  
 
   for (int r=1; r<=people.n_rows; r++)//people.n_rows
  {
    int run = r;
    cout << "****************************************" << endl;
    cout << "Doing for run= " << run << endl;
    cout << "N_cent " << N_cent << endl;
    cout << "****************************************" << endl;
  
    
    rand_split(run);
    field<string> peo_train;
    field<string> peo_test;
    std::stringstream train_list;
    train_list<< "./run" << run << "/train_list_run"<< run << ".dat";
    std::stringstream test_list;
    test_list<< "./run" << run << "/test_list_run"<< run << ".dat";
    peo_train.load( train_list.str() );
    peo_test.load(  test_list.str() );
    
    peo_train.print("People Train");
    
    cout << "Calculating Universal GMM" << endl;
    fisher_vector fisher_vector(single_path, multi_path, actionNames, co, ro);
    fisher_vector.optflow_create_universal_gmm(peo_train, N_cent, run); 

   }



}


void
rand_split(int run)
{
  
  field<string> people;
  people.load(peopleList);
  uword num_peo = people.n_rows;
  //arma_rng::set_seed_random();
  
  field<string> rand_people_train(num_peo - 1 );
  field<string> rand_people_test(1);
  rand_people_test(0) = people (run - 1);
  
  int k=0;
  for (uword i=0; i<num_peo; ++i)
  {
    if (i!=run-1)
    {
      rand_people_train(k) = people(i);
      k++;
    }
    
  }
  std::stringstream train_list;
  train_list<< "./run" << run << "/train_list_run"<< run << ".dat";
  
  std::stringstream test_list;
  test_list<< "./run" << run << "/test_list_run"<< run << ".dat";
  
  //rand_people_train.print("train_list");
  //rand_people_test.print("test_list");
  
  rand_people_train.save( train_list.str() );
  rand_people_test.save( test_list.str() );
  
}


  
